
<template>
  <canvas ref="canvasRef" class="jzd-canvas" :style="{
    width: width + 'px', height: height + 'px',
    transform: 'scale(' + (1 / scale) + ')', 'transform-origin': '0 0',
    zIndex: zIndex
  }" @mousedown="handleStartWriting($event)" @mousemove="handleOnWriting($event)" @mouseup="handleStopWriting($event)"
    @touchstart="handleStartWriting($event)" @touchmove="handleOnWriting($event)" @touchend="handleStopWriting($event)"
    @mouseenter="mouseInCanvas = true" @mouseleave="handleStopWriting($event); mouseInCanvas = false"></canvas>
  <div v-if="mouseInCanvas && mode === 'eraser'" class="jzd-eraser" :style="{
      left: (mousePos.x - size / 2) + 'px', top: (mousePos.y - size / 2) + 'px',
      width: size + 'px', height: size + 'px',
      zIndex: zIndex
    }
    "></div>
</template>

<script lang='ts' setup>
import { startWriting, writingCurve, stopWriting, erase, clear, getOffsetPosition, drawShape, writingRoundRect, writingEllipse, writingRegtri, writingRighttri, writingArrowRight } from './BoardWriting'
import { onMounted, ref } from 'vue'
import { useBoardStore } from './board';

const boardStore = useBoardStore();

const canvasRef = ref();
let canvasContext: any = null;
const props = defineProps({
  boardWidth: {
    type: Number, required: true
  },
  boardHeight: {
    type: Number, required: true
  },
  scale: {
    type: Number, default: 1
  },
  isDraw: {
    type: Boolean, default: true,
  },
  mode: {
    type: String, default: 'pen',
  },
  color: {
    type: String, default: '#FF0000',
  },
  size: {
    type: Number, default: 4,
  },
  zIndex: {
    type: Number, default: 0,
  },
  outType: {
    type: String, default: 'snapshot',
  }
});

const width = ref(0);
const height = ref(0);

onMounted(() => {
  initCanvas();
});

function initCanvas() {
  width.value = props.boardWidth * props.scale;
  height.value = props.boardHeight * props.scale;
  canvasRef.value.width = width.value;
  canvasRef.value.height = height.value;

  canvasContext = canvasRef.value.getContext('2d');
  if (!canvasContext) return;
  canvasContext.lineCap = 'round';
  canvasContext.lineJoin = 'round';
}

const mouseInCanvas = ref(false);
const mousePos = ref({ x: 0, y: 0 });

const isWritting = ref(false);


function handleStartWriting(e:any) {
  if (!props.isDraw) return;
  isWritting.value = true;
  const params = { mode: props.mode, color: props.color, size: props.size, scale: props.scale }; //, width: width.value, height: height.value
  startWriting(canvasRef.value, canvasContext, params, e);
  if (props.mode === 'pen' || props.mode === 'flupen') handleOnWriting(e);
  e.preventDefault();
}
function handleOnWriting(e:any) {
  if (!props.isDraw) return;
  if (mouseInCanvas.value) {
    mousePos.value = getOffsetPosition(canvasRef.value, e, 1);
  }
  if (!isWritting.value) return;
  switch (props.mode) {
    case 'arrowright':
      writingArrowRight(e);
      break;
    case 'roundrect':
      writingRoundRect(e);
      break;
    case 'ellipse':
      writingEllipse(e);
      break;
    case 'regtri':
      writingRegtri(e);
      break;
    case 'righttri':
      writingRighttri(e);
      break;
    case 'eraser':
      erase(canvasRef.value, canvasContext, {
        width: width.value, height: height.value, scale: props.scale, size: props.size
      }, e);
      break;
    case 'pen':
    case 'flupen':
    default:
      writingCurve(e);
      break;
  }
  e.preventDefault();
}
const emit = defineEmits(["writing"])

function handleStopWriting(e:any) {
  if (!props.isDraw) return;
  handleOnWriting(e);
  e.preventDefault();
  isWritting.value = false;
  const record = stopWriting(e);
  if (record) {
    if (props.outType === 'snapshot') {
      const url = getDataUrl();
      boardStore.addElement(url);
    } else {
      emit('writing', record);
    }
  }
}

function getDataUrl() {
  return canvasRef.value.toDataURL();
}
function setDataUrl(dataUrl:any) {
  if (!canvasContext) return;
  if (dataUrl) {
    canvasContext.globalCompositeOperation = 'source-over'
    canvasContext.globalAlpha = 1;
    const img = new Image()
    img.src = dataUrl
    img.onload = () => {
      canvasContext.clearRect(0, 0, width.value, height.value);
      canvasContext.drawImage(img, 0, 0);
    }
  } else {
    canvasContext.clearRect(0, 0, width.value, height.value);
  }
}

function clearWriting() {
  if (!canvasContext) return;
  clear(canvasContext, { width: width.value, height: height.value });
}
function setSnapshot(dataUrl:any) {
  setDataUrl(dataUrl);
  // boardStore.addElement(dataUrl);
}

function writeShape(ele:any) {
  if (!canvasContext) return;
  drawShape(canvasContext, ele);
  setTimeout(() => {
    const url = getDataUrl();
    boardStore.addElement(url);
  }, 0);
}

defineExpose({
  clearWriting: clearWriting,
  setSnapshot: setSnapshot,
  writeShape: writeShape
});

</script>

<style scoped>
.jzd-canvas {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
}

.jzd-eraser {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid #ffffff80;
  background-color: #23e90850;
  border-radius: 50%;
  pointer-events: none;
}
</style>